home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2008 February / PCWFEB08.iso / Software / Freeware / Miro 1.0 / Miro_Installer.exe / xulrunner / python / guide.py < prev    next >
Encoding:
Python Source  |  2007-11-12  |  7.5 KB  |  231 lines

  1. # Miro - an RSS based video player application
  2. # Copyright (C) 2005-2007 Participatory Culture Foundation
  3. #
  4. # This program is free software; you can redistribute it and/or modify
  5. # it under the terms of the GNU General Public License as published by
  6. # the Free Software Foundation; either version 2 of the License, or
  7. # (at your option) any later version.
  8. #
  9. # This program is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. # GNU General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU General Public License
  15. # along with this program; if not, write to the Free Software
  16. # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  17.  
  18. import resources
  19. from database import DDBObject
  20. from template import fillStaticTemplate
  21. from httpclient import grabURL
  22. from urlparse import urlparse, urljoin
  23. from xhtmltools import urlencode
  24. from copy import copy
  25. from util import returnsUnicode, unicodify, checkU
  26. import re
  27. import app
  28. import config
  29. import indexes
  30. import menu
  31. import prefs
  32. import threading
  33. import urllib
  34. import eventloop
  35. import views
  36. import logging
  37. import httpclient
  38. from gtcache import gettext as _
  39. from HTMLParser import HTMLParser,HTMLParseError
  40. import iconcache
  41.  
  42. HTMLPattern = re.compile("^.*(<head.*?>.*</body\s*>)", re.S)
  43.  
  44. def isPartOfGuide(url, guideURL, allowedURLs = None):
  45.     """Return if url is part of a channel guide where guideURL is the base URL
  46.     for that guide.
  47.     """
  48.     if guideURL == "*":
  49.         return True
  50.     elif allowedURLs is None:
  51.         guideHost = urlparse(guideURL)[1]
  52.         urlHost = urlparse(url)[1]
  53.         return urlHost.endswith(guideHost)
  54.     else:
  55.         if isPartOfGuide(url, guideURL):
  56.             return True
  57.         for altURL in allowedURLs:
  58.             if isPartOfGuide(url, altURL):
  59.                 return True
  60.         return False
  61. class ChannelGuide(DDBObject):
  62.     ICON_CACHE_SIZES = [
  63. #        (20, 20),
  64.     ]
  65.     def __init__(self, url=None, allowedURLs = None):
  66.         checkU(url)
  67.         if allowedURLs is None:
  68.             self.allowedURLs = []
  69.         else:
  70.             self.allowedURLs = allowedURLs
  71.         if url is None and allowedURLs is None:
  72.             self.allowedURLs = config.get(prefs.CHANNEL_GUIDE_ALLOWED_URLS).split()
  73.         self.allowedURLs.append(config.get(prefs.CHANNEL_GUIDE_FIRST_TIME_URL))
  74.         self.url = url
  75.         self.updated_url = url
  76.         self.title = None
  77.         self.lastVisitedURL = None
  78.         self.iconCache = iconcache.IconCache(self, is_vital = True)
  79.         self.favicon = None
  80.         self.firstTime = True
  81.  
  82.         DDBObject.__init__(self)
  83.         self.downloadGuide()
  84.  
  85.     def onRestore(self):
  86.         self.lastVisitedURL = None
  87.         if (self.iconCache == None):
  88.             self.iconCache = iconcache.IconCache (self, is_vital = True)
  89.         else:
  90.             self.iconCache.dbItem = self
  91.             self.iconCache.requestUpdate(True)
  92.         if self.getDefault():
  93.             self.allowedURLs = config.get(prefs.CHANNEL_GUIDE_ALLOWED_URLS).split()
  94.             self.allowedURLs.append(config.get(prefs.CHANNEL_GUIDE_FIRST_TIME_URL))
  95.         else:
  96.             self.allowedURLs = []
  97.         self.downloadGuide()
  98.  
  99.  
  100.     def __str__(self):
  101.         return "Miro Guide <%s>" % (self.url,)
  102.  
  103.     def makeContextMenu(self, templateName, view):
  104.         menuItems = [
  105.             (lambda: app.delegate.copyTextToClipboard(self.getURL()),
  106.                 _('Copy URL to clipboard')),
  107.         ]
  108.         if not self.getDefault():
  109.             i = (lambda: app.controller.removeGuide(self), _('Remove'))
  110.             menuItems.append(i)
  111.         return menu.makeMenu(menuItems)
  112.  
  113.     def remove(self):
  114.         if self.iconCache is not None:
  115.             self.iconCache.remove()
  116.             self.iconCache = None
  117.         DDBObject.remove(self)
  118.  
  119.     def isPartOfGuide(self, url):
  120.         return isPartOfGuide(url, self.getURL(), self.allowedURLs)
  121.  
  122.     def getURL(self):
  123.         if self.url is not None:
  124.             return self.url
  125.         else:
  126.             return config.get(prefs.CHANNEL_GUIDE_URL)
  127.  
  128.     def getFirstURL(self):
  129.         if self.url is not None:
  130.             return self.url
  131.         else:
  132.             return config.get(prefs.CHANNEL_GUIDE_FIRST_TIME_URL)
  133.  
  134.     def getLastVisitedURL(self):
  135.         if self.lastVisitedURL is not None:
  136.             logging.info("First URL is %s"%self.lastVisitedURL)
  137.             return self.lastVisitedURL
  138.         else:
  139.             if self.firstTime:
  140.                 self.firstTime = False
  141.                 logging.info("First URL is %s"%self.getFirstURL())
  142.                 return self.getFirstURL()
  143.             else:
  144.                 logging.info("First URL is %s"%self.getURL())
  145.                 return self.getURL()
  146.  
  147.     def getDefault(self):
  148.         return self.url is None
  149.  
  150.     # For the tabs
  151.     @returnsUnicode
  152.     def getTitle(self):
  153.         if self.title:
  154.             return self.title
  155.         elif self.getDefault():
  156.             return _('Miro Guide')
  157.         else:
  158.             return self.getURL()
  159.  
  160.     def guideDownloaded(self, info):
  161.         self.updated_url = unicode(info["updated-url"])
  162.         try:
  163.             parser = GuideHTMLParser(self.updated_url)
  164.             parser.feed(info["body"])
  165.             parser.close()
  166.         except:
  167.             pass
  168.         else:
  169.             self.title = unicode(parser.title)
  170.             self.favicon = unicode(parser.favicon)
  171.             self.iconCache.requestUpdate()
  172.             self.signalChange()
  173.  
  174.     def guideError (self, error):
  175.         pass
  176.  
  177.     def downloadGuide(self):
  178.         httpclient.grabURL(self.getURL(), self.guideDownloaded, self.guideError)
  179.  
  180.     @returnsUnicode
  181.     def getIconURL(self):
  182.         if self.iconCache.isValid():
  183.             path = self.iconCache.getResizedFilename(20, 20)
  184.             return resources.absoluteUrl(path)
  185.         else:
  186.             return resources.url("images/channelguide-icon-tablist.png")
  187.  
  188.     def getThumbnailURL(self):
  189.         if self.favicon:
  190.             return self.favicon
  191.         else:
  192.             if self.updated_url:
  193.                 parsed = urlparse(self.updated_url)
  194.             else:
  195.                 parsed = urlparse(self.getURL())
  196.             return parsed[0] + u"://" + parsed[1] + u"/favicon.ico"
  197.  
  198. # Grabs the feed link from the given webpage
  199. class GuideHTMLParser(HTMLParser):
  200.     def __init__(self, url):
  201.         self.title = None
  202.         self.in_title = False
  203.         self.baseurl = url
  204.         self.favicon = None
  205.         HTMLParser.__init__(self)
  206.  
  207.     def handle_starttag(self, tag, attrs):
  208.         attrdict = {}
  209.         for (key, value) in attrs:
  210.             attrdict[key] = value
  211.         if tag == 'title' and self.title == None:
  212.             self.in_title = True
  213.             self.title = u""
  214.         if (tag == 'link' and attrdict.has_key('rel') and
  215.             attrdict.has_key('type') and attrdict.has_key('href') and
  216.             'icon' in attrdict['rel'].split(' ') and
  217.             attrdict['type'].startswith("image/")):
  218.  
  219.             self.favicon = urljoin(self.baseurl,attrdict['href']).decode('ascii', 'ignore')
  220.  
  221.     def handle_data(self, data):
  222.         if self.in_title:
  223.             self.title += data
  224.  
  225.     def handle_endtag(self, tag):
  226.         if tag == 'title' and self.in_title:
  227.             self.in_title = False
  228.  
  229. def getGuideByURL(url):
  230.     return views.guides.getItemWithIndex(indexes.guidesByURL, url)
  231.